package cn.xinfei.xdecision.engine.runner.executor.handler;

import cn.xinfei.xdecision.common.model.component.decisiontable.DecisionTablesDetailCondition;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesDetailVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesResultVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesVersionVo;
import cn.xinfei.xdecision.common.model.enginex.runner.ExpressionParam;
import cn.xinfei.xdecision.engine.runner.context.PipelineContext;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.expressions.ExpressExecutor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class DecisionTableNodeHandler {

    @Autowired
    @Qualifier("decisionTableThreadPool")
    public ExecutorService decisionTableThreadPool;

    @Value("${xdecision.timeout.decisionTableThreadWaitingTime:20}")
    private long decisionTableThreadWaitingTime;

    //执行整个决策表返回决策结果数据
    public Object executeDecisionTables(DecisionTablesVersionVo versionVo) {

        XDecisionContext context = XDecisionContext.getContext();
        PipelineContext pipelineContext = context.getPipelineContext();
        Future<Integer> top = null;
        Future<Integer> left = null;
        //取出行列索引
        Integer row = -1;
        Integer column = -1;
        List<DecisionTablesDetailVo> leftDetailVo = versionVo.getLeftDetailVo();
        if (CollectionUtils.isEmpty(leftDetailVo) || (leftDetailVo.size() == 1 && StringUtils.isBlank(leftDetailVo.get(0).getFieldCode()) && CollectionUtils.isEmpty(leftDetailVo.get(0).getChildren()))) {
            row = 0;
        } else {
            //左侧执行
            left = decisionTableThreadPool.submit(() -> executeDecisionTablesDetail("row", leftDetailVo, pipelineContext));
        }
        //右侧执行
        List<DecisionTablesDetailVo> topDetailVo = versionVo.getTopDetailVo();
        if (CollectionUtils.isEmpty(topDetailVo) || (topDetailVo.size() == 1 && StringUtils.isBlank(topDetailVo.get(0).getFieldCode()) && CollectionUtils.isEmpty(topDetailVo.get(0).getChildren()))) {
            column = 0;
        } else {
            top = decisionTableThreadPool.submit(() -> executeDecisionTablesDetail("column", topDetailVo, pipelineContext));
        }
        try {
            if (row == -1) {
                row = left.get(decisionTableThreadWaitingTime, TimeUnit.SECONDS);
            }
            if (column == -1) {
                column = top.get(decisionTableThreadWaitingTime, TimeUnit.SECONDS);
            }
        } catch (InterruptedException |ExecutionException |TimeoutException e) {
            log.info("并行规则异常,versionVo={}", versionVo);
            //todo shiyusen 埋点监控
        }

        //行列值均取到的进行处理
        if (row >= 0 && column >= 0) {
            //根据行列去结果集中找结果返回
            DecisionTablesResultVo resultSet = versionVo.getResultSet();
            if (row < resultSet.getRows() && column < resultSet.getColumns()) {
                String resultValue = resultSet.getResultValue();
                JSONArray array = JSON.parseArray(resultValue);
                JSONArray rowArray = JSON.parseArray(JSON.toJSONString(array.get(row)));
                return rowArray.get(column);
            }
        } else {
            log.warn("决策表行列定位失败,没有覆盖所有分支，row={},column={}", row, column);
        }
        return null;
    }

    //执行决策表的条件获取
    public Integer executeDecisionTablesDetail(String type, List<DecisionTablesDetailVo> decisionTablesDetailList, PipelineContext context) {
        int size = decisionTablesDetailList.size();
        AtomicInteger index=new AtomicInteger(-1);
        for (int i = 0; i < size; i++) {
            DecisionTablesDetailVo decisionTablesDetailVo = decisionTablesDetailList.get(i);
            //调用drools执行
//            int result = recursionExecuteDecisionTablesDetail(decisionTablesDetailVo, paramMap);
            //调用不使用drools执行
            int hitIndex = executeDecisionTablesDetail(decisionTablesDetailVo, index);
            Long id = decisionTablesDetailVo.getId();
            String fieldCode = decisionTablesDetailVo.getFieldCode();
            Integer dimensionality = decisionTablesDetailVo.getDimensionality();
            log.warn("决策表匹配出行列坐标 type={},index={},id={},dimensionality={},fieldCode={}", type, index, id, dimensionality, fieldCode);
            if (hitIndex >= 0) {
                return hitIndex;
            }
        }
//        for (DecisionTablesDetailVo decisionTablesDetailVo : decisionTablesDetailList) {
//            //调用drools执行
////            int result = recursionExecuteDecisionTablesDetail(decisionTablesDetailVo, paramMap);
//            //调用不使用drools执行
//            int index = executeDecisionTablesDetail(decisionTablesDetailVo,0);
//            Long id = decisionTablesDetailVo.getId();
//            String fieldCode = decisionTablesDetailVo.getFieldCode();
//            Integer dimensionality = decisionTablesDetailVo.getDimensionality();
//            log.warn("决策表匹配出行列坐标 type={},index={},id={},dimensionality={},fieldCode={}", type, index, id,dimensionality, fieldCode);
//            if (index >= 0) {
//                return index;
//            }
//        }
        return -1;
    }

    //不使用drools的执行
    private int executeDecisionTablesDetail(DecisionTablesDetailVo decisionTablesDetailVo, AtomicInteger deep) {
        //获取需要执行的条件列表
        List<DecisionTablesDetailCondition> conditionList = decisionTablesDetailVo.getConditionList();
        String fieldEn = decisionTablesDetailVo.getFieldCode();
        String logical = decisionTablesDetailVo.getLogicalSymbol();
        boolean result = false;
        //根据不通关系进行处理
        switch (logical) {
            case "||":
                result = false;
                for (DecisionTablesDetailCondition condition : conditionList) {
                    ExpressionParam expressionParam = new ExpressionParam();
                    BeanUtils.copyProperties(condition, expressionParam);
                    expressionParam.setFieldEn(fieldEn);
                    try {
                        boolean expressionResult = ExpressExecutor.getExpressionResult(expressionParam);
                        log.info("{}:{} {} {},result={}", condition.getDetailId(), expressionParam.getFieldEn(), expressionParam.getOperator(), expressionParam.getValue(), expressionResult);
                        if (expressionResult) {
                            result = true;
                            break;
                        }
                    } catch (Throwable e) {
                        log.error("DecisionTablesNode，runNode执行异常：expressionParam{}", expressionParam);
                        result = false;
                        break;
                    }
                }
                break;
            case "&&":
                result = true;
                for (DecisionTablesDetailCondition condition : conditionList) {
                    ExpressionParam expressionParam = new ExpressionParam();
                    BeanUtils.copyProperties(condition, expressionParam);
                    expressionParam.setFieldEn(fieldEn);
                    try {
                        boolean expressionResult = ExpressExecutor.getExpressionResult(expressionParam);
                        log.info("{}:{} {} {},result={}", condition.getDetailId(), expressionParam.getFieldEn(), expressionParam.getOperator(), expressionParam.getValue(), expressionResult);
                        if (!expressionResult) {
                            result = false;
                            break;
                        }
                    } catch (Throwable e) {
                        log.error("DecisionTablesNode，runNode执行异常：expressionParam{}", expressionParam);
                        result = false;
                        break;
                    }
                }
                break;
        }
        Integer type = decisionTablesDetailVo.getNodeType();
        if(type==2){
            //遇到叶子节点+1
            deep.incrementAndGet();
        }
        //如果本节点符合则执行后续节点
        if (result) {
            List<DecisionTablesDetailVo> children = decisionTablesDetailVo.getChildren();
            if (type != null) {
                switch (type) {
                    //普通节点符合，让子节点继续执行。
                    case 1:
                        if (children != null && children.size() > 0) {
                            for (int i = 0; i < children.size(); i++) {
                                DecisionTablesDetailVo child = children.get(i);
                                int executeResult = this.executeDecisionTablesDetail(child, deep);
                                if (executeResult >= 0) {
                                    return executeResult;
                                }
                            }
                        }else{
//                            System.out.println();
                        }
                        break;
                    //叶子节点符合，返回叶子节点的值。
                    case 2:
                        return deep.get();
//                        return decisionTablesDetailVo.getIndexValue();
                    default:
                        break;
                }
            }
        }
        return -1;
    }

}
